# project.py

# vase is 3.29 x 1.39 at the widest part.
#
# engrave should be 2.5715 wide, centered 2.052" above bottom of vase.
# 
# engrave_1 geometric chuck settings to get the right size:
#   SR: 0.34666
#   e1: 0.19413
#   e2: 0.86665

from __future__ import division

import math
import itertools
import time

from ot_simulator import project
from ot_simulator.cutting_pass import cutting_pass, rapid_funs
from ot_simulator.setup import setup
from ot_simulator.component import *

from ot_simulator.cutting_pass.debuggers import graph, minmax

from ot_simulator.template.param_funs import (
    param_ref, param_fun, param_eval, fun_value, get_param,
  )
from ot_simulator.template.template_funs import (template_fun, file_multi_num,
                                                 frange)

from ot_simulator.output.tormach import pcnc_1100
from ot_simulator.output.outputer import file

#Tool_radius = 0.7555 / 2       # HSS router bit
Tool_radius = 0.6275 / 2        # New carbide router bit

Comments = (
    'Align bottom of all tools to center at free end of work.',
)

def body_offset_fn(point, params):
    sr = get_param(params, 'sr')
    #if 'sr' in params:
    #    sr = get_param(params, 'sr')
    #else:
    #    sr = 0.0
    if sr >= -1.90196:
        offset = Tool_radius
        if sr > -1.405:      # move over for shoulder
            offset += get_param(params, 'roughing_offset')
    else:
        offset = -Tool_radius
    return point.move(x=offset)

e_template = template_fun(file_multi_num('e_engrave_template.csv'))

sr_template = template_fun(file_multi_num('sr_template.csv'))

Graph1 = graph(x = param_ref('capture.x'), y = param_ref('capture.y'))
Graph2 = graph(x = param_ref('capture.x'),
               y = param_eval('($headstock.index - 90.0)/35.0'))
Capture_x = minmax("capture.x", param_ref('capture.x'))
Capture_y = minmax("capture.y", param_ref('capture.y'))
Capture_z = minmax("capture.z", param_ref('capture.z'))

#    minmax("zero_capture.x", param_ref('zero_capture.x')),
#    minmax("zero_capture.y", param_ref('zero_capture.y')),
#    minmax("zero_capture.z", param_ref('zero_capture.z')),
#    minmax("sr_capture.x", param_ref('sr_capture.x')),
#    minmax("sr_capture.y", param_ref('sr_capture.y')),
#    minmax("sr_capture.z", param_ref('sr_capture.z')),
#    minmax("tool_capture.x", param_ref('tool_capture.x')),
#    minmax("tool_capture.y", param_ref('tool_capture.y')),
#    minmax("tool_capture.z", param_ref('tool_capture.z')),
#    minmax("slide_rest._combined_sr", param_ref('slide_rest._combined_sr')),

body_setup = \
  setup('body',
        (
            headstock(),
            elliptical_chuck(
              index = param_ref('headstock.index'),
              e = param_eval('$e_template(-$sr)'),
              sr = param_ref('slide_rest._surface_offset')),
        ),
        (
            slide_rest(_surface_offset = param_eval('$sr_template(-$sr)'),
                       tool_offset = 
                         param_eval(
                           'max($slide_rest._surface_offset + $roughing_offset,'
                           '$cutting_depth)')),
            swivel(axis = 'X',
                   angle = param_ref('elliptical_chuck.tangent')),
        ),
        (cutting_pass.update_params(
             speed = 5000,
             feed = 20,  # slower than this starts to overheat

             # This is crazy: X->Y, Y->Z, Z->X, C->A
             clear1 = "Y6.0 C0", clear2 = "X0 Y3 C0",
             pos1 = "X0 Y3 Z0.3438", out = "Y3",

             # scale by 0.7955
             #start_gcode =
             #  ('G51 X0.7955 Y0.7955 Z0.7955 A1.0',),

             tool = 1, tool_desc = '3/4" straight router bit',
             roughing_offset = 0.03,
             z_inc = param_ref('z_inc_rough'),
             index_inc = param_ref('index_inc_rough'),
             lineno = 1000,
             e_template = fun_value(e_template),
             sr_template = fun_value(sr_template),
           ),
         cutting_pass.add_debuggers(
           ),
         cutting_pass.add_offset_fn(body_offset_fn),
         cutting_pass.sequence(
           cutting_pass.step(
               'cutting_depth',
               param_eval('-$cutting_depth_inc'),
                          #1.90 - $cutting_depth_inc   # pine
               param_eval('2.05 - $cutting_depth_inc'),
               param_eval('0.3125 + $roughing_offset')),
           cutting_pass.update_params(
               feed = 10,  # the Tormach acts goofy at 60
               pos1 = "X0 Y3 Z0.3137",
               cutting_depth = 0.0,
               cutting_depth_inc = 0.0,
               roughing_offset = 0.0,
               index_inc = param_ref('index_inc_finish'),
               z_inc = param_ref('z_inc_finish'),
               lineno = 2000)),
         cutting_pass.cut(),
         cutting_pass.step('index',
                           param_ref('index_inc'),
                           90.0,
                           param_eval('450.0 - $index_inc')),
         cutting_pass.gen_pass(
             rapid_funs.rapid1('Z', param_eval('$cutting_depth_inc + 0.10'))),
         cutting_pass.step('sr',
                           param_ref('z_inc'),
                           0,
                           -0.99707,   # be sure to hit the corner of the neck!
                           -4.5),
         cutting_pass.generate()
        ),
        full  = dict(
                  #cutting_depth_inc = 0.3055,  # pine
                  cutting_depth_inc = 0.3415,   # 5 roughing passes
                  #cutting_depth_inc = 0.2846,  # 6 roughing passes
                  z_inc_rough = -0.15, index_inc_rough = 20,
                  z_inc_finish = -0.02, index_inc_finish = 2.5),
        quick = dict(
                  cutting_depth_inc = 0.52,
                  z_inc_rough = -0.5625, index_inc_rough = 30,
                  z_inc_finish = -0.30, index_inc_finish = 20),
    )

front_engraving_setup = \
  setup('front_engraving',
        (
            headstock(
              index = 
                param_eval(
                  'math.degrees($capture.y / '
                    '($slide_rest._surface_offset + $elliptical_chuck.e)) '
                  '+ 90.0')),

            elliptical_chuck(
                index = param_ref('headstock.index'),
                e = param_eval('$e_template(-$slide_rest.sr)'),
                sr = param_ref('slide_rest._surface_offset')),
        ),
        (
            # calculate geometric cutting frame
            lathe_to_cutting_frame(
              ( # work stack
               headstock(name = "cf_hs"),
               geometric_chuck(name = "gc1",
                               index = param_ref('cf_hs.index'),
                               e = 0.19413,
                               n = 8,
                               d = 5,
                               direction = 'out'),
               geometric_chuck(name = "gc2",
                               index = param_ref('gc1.index_out'),
                               e = 0.86665,
                               n = 3,
                               direction = 'out'),
              ), ( # tool stack
               slide_rest(angle = 90.0,
                          sr = -0.34666),
            )),

            # capture the x, y, z positions of the cutting_frame
            capture(),

            # reset (start over)
            reset(),

            # Start of the real tool stack
            slide_rest(sr = param_eval('-2.348 + $capture.x'),
                       _surface_offset = 
                         param_eval('$sr_template(-$slide_rest.sr)'),
                       tool_offset = param_eval(
                         '$slide_rest._surface_offset + $offset')),

            swivel(axis='X',
                   angle=param_ref('elliptical_chuck.tangent')),
        ),
        (cutting_pass.update_params(
             speed = 5000,
             feed = 8,   # a little rough at feed=30
                         # still maybe a little rough at F10

             # This is crazy: X->Y, Y->Z, Z->X, C->A
             clear1 = "Y6.0 C0", clear2 = "X0 Y3 C0",
             pos1 = "X0 Y3 Z-3.7554", out = "Y3",

             tool = 2, tool_desc = 'V shaped router bit',
             offset = -0.03,
             lineno = 3000,
             e_template = fun_value(e_template),
             sr_template = fun_value(sr_template),
           ),
         cutting_pass.add_debuggers(
             #  Graph1, Capture_x, Capture_y, Capture_z,
           ),
         cutting_pass.cut(),  # this cut only has 1 pass
         cutting_pass.gen_pass(rapid_funs.rapid1('Z', 0.20)),
         cutting_pass.step('index', param_ref('index_inc'), 0.0, 24.0 * 360.0),
         cutting_pass.generate()
        ),
        full  = dict(index_inc = 0.5),
        quick = dict(index_inc = 60),
    )

rear_engraving_setup = \
  setup('rear_engraving',
        (
            headstock(
              index = 
                param_eval(
                  'math.degrees($capture.y / '
                    '($slide_rest._surface_offset + $elliptical_chuck.e))'
                  '- 90.0')),

            elliptical_chuck(
              index=param_ref('headstock.index'),
              e=param_eval('$e_template(-$slide_rest.sr)'),
              sr=param_ref('slide_rest._surface_offset')),

            #Graph,
        ),
        (
            # calculate geometric cutting frame
            lathe_to_cutting_frame(
              ( # Start of lathe_to_cutting_frame work stack
                headstock(name="cf_hs"),
                geometric_chuck(name="gc1",
                                index=param_ref('cf_hs.index'),
                                e = 0.5656,
                                n = 3,
                                direction = 'out',
                                nosewheel_index = 0.0),
                geometric_chuck(name="gc2",
                                index=param_ref('gc1.index_out'),
                                e = 0.5656,
                                n = 3,
                                direction = 'out'),
              ), ( # Start of lathe_to_cutting_frame tool stack
                slide_rest(angle=90.0,
                           sr=-0.1885),
            )),

            # capture the x, y, z positions of the cutting_frame
            capture(),

            # reset (start over)
            reset(),

            # Start of the real tool stack
            slide_rest(sr = param_eval('-2.514 + $capture.x'),
                       _surface_offset =
                         param_eval('$sr_template(-$slide_rest.sr)'),
                       tool_offset = param_eval(
                         '$slide_rest._surface_offset + $offset')),

            swivel(axis='X',
                   angle=param_ref('elliptical_chuck.tangent')),
        ),
        (cutting_pass.update_params(
             speed = 5000,
             feed = 8,   # a little rough at feed=30
                         # still maybe a little rough at F10

             # This is crazy: X->Y, Y->Z, Z->X, C->A
             clear1 = "Y6.0 C180", clear2 = "X0 Y3 C180",
             pos1 = "X0 Y3 Z-3.8337 C180", out = "Y3",

             tool = 2, tool_desc = 'V shaped router bit',
             offset = -0.03,
             lineno = 4000,
             e_template = fun_value(e_template),
             sr_template = fun_value(sr_template),
           ),
         cutting_pass.add_debuggers(
              Graph1, Capture_x, Capture_y, Capture_z,
           ),
         cutting_pass.cut(),  # this cut only has 1 pass
         cutting_pass.gen_pass(rapid_funs.rapid1('Z', 0.20)),
         cutting_pass.step('index', param_ref('index_inc'), 0.0, 9.0 * 360.0),
         cutting_pass.generate()
        ),
        full  = dict(index_inc = 0.5),
        quick = dict(index_inc = 60),
    )

vase_piece = project.piece('Elliptical Vase',
                           body_setup,
                           front_engraving_setup,
                           rear_engraving_setup)

vase_piece.add_comments(*Comments)

vase_project = project.project('vase', vase_piece)

def dump(msg, x):
    print msg, x
    return x

def test_pickle(filename):
    import cPickle as pickle
    with open(filename, 'wb') as f:
        pickle.dump(vase_project, f, pickle.HIGHEST_PROTOCOL)

def full(filename='vase_full.nc'):
    start_time = time.time()
    dest_machine = pcnc_1100(file())
    vase_piece.run('full', dest_machine, filename)
    print "elapsed time", time.time() - start_time

def quick(filename='vase_quick.nc'):
    start_time = time.time()
    dest_machine = pcnc_1100(file())
    vase_piece.run('quick', dest_machine, filename)
    print "elapsed time", time.time() - start_time

